import { DeleteOutlined } from '@ant-design/icons'
import { useRefValue } from '@gnlab/utils/env-react'
import { message, Input, Button, Typography } from 'antd'
import { ReactComponent as MpIcon } from '@/desktop/assets/mini-program.svg'
import { ReactComponent as VideonumIcon } from '@/desktop/assets/videonum.svg'
import { ImportantEditModal } from '@/desktop/components'
import Link from '@/desktop/components/link'
import { useStreams } from '@/lib/utils'
import type { SendItem } from '@/sdk/host'
import services from '@/services'
import './batch-send.module.less'

type EditSendItem = SendItem & { id: number }

export function BatchSendHandling() {
  const [handlingItems, setHandlingItems] = useState<SendItem[] | null>(null)
  const handlingItemsRef = useRefValue(handlingItems)
  const onFinish = () => setHandlingItems(null)

  useEffect(() => {
    if (handlingItemsRef.current) return void message.warning('有正在处理的消息，无法再次发送')
    const off = services.sdkHost.instance.on('batch-send-editing', (items: SendItem[]) =>
      setHandlingItems(items),
    )
    return off
  }, [handlingItemsRef])

  return <BatchSend initialItems={handlingItems} onFinish={onFinish} />
}

function BatchSend(props: { initialItems: SendItem[] | null; onFinish: () => void }) {
  const { initialItems, onFinish } = props

  return <ImportantEditModal
    open={!!initialItems}
    onCancel={onFinish}
    title="发送消息"
    width="600px"
  >
    {initialItems ? <BatchSendContent initialItems={initialItems} onFinish={onFinish} /> : null}
  </ImportantEditModal>
}

function BatchSendContent(props: { initialItems: SendItem[]; onFinish: () => void }) {
  const { initialItems, onFinish } = props

  // initialItems 只会在组件初始化时影响 items
  const [items, setItems] = useState(() =>
    initialItems.map((item, index) => ({ ...item, id: index })),
  )

  function update(id: number, item: EditSendItem) {
    setItems(items => {
      const index = items.findIndex(v => v.id === id)
      if (index === -1) return items

      const newItems = [...items]
      newItems[index] = item
      return newItems
    })
  }

  function remove(id: number) {
    setItems(items => items.filter(v => v.id !== id))
  }

  const send = useCallback(() => {
    void services.sdkHost.instance.batchSend(items)
    onFinish()
  }, [items, onFinish])

  return <>
    <main styleName="records">
      {items.map(item => <SendRecord
        key={item.id}
        item={item}
        onUpdate={update}
        onRemove={remove}
      />)}
    </main>
    <footer>
      <Button onClick={onFinish}>取消</Button>
      <Button type="primary" disabled={!items.length} onClick={send}>
        发送
      </Button>
    </footer>
  </>
}

function SendRecord(props: {
  item: EditSendItem
  onUpdate: (id: number, item: EditSendItem) => void
  onRemove: (id: number) => void
}) {
  const { item, onUpdate, onRemove } = props

  const update = useCallback(
    (data: unknown) => {
      // @ts-ignore data 为目标条目数据类型
      onUpdate(item.id, { ...item, data })
    },
    [item, onUpdate],
  )

  const [title, rendered] = getRendered(item, update)

  return <div styleName="record">
    <header>
      {/*
        TODO: 排序功能稍后实现
        <MenuOutlined styleName="sort" />
      */}
      <div styleName="title">{title}</div>
      <DeleteOutlined styleName="remove" onClick={() => onRemove(item.id)} />
    </header>
    <div styleName="content">{rendered}</div>
  </div>
}

function getRendered(item: EditSendItem, update: (data: unknown) => void): [string, JSX.Element] {
  switch (item.type) {
    case 'text':
      return ['文本', <TextRecord key={item.id} data={item.data} onUpdate={update} />]
    case 'image':
      return ['图片', <ImageRecord key={item.id} data={item.data} />]
    case 'file':
      return ['文件', <FileRecord key={item.id} data={item.data} />]
    case 'video':
      return ['视频', <VideoRecord key={item.id} data={item.data} />]
    case 'link':
      return ['链接卡片', <LinkRecord key={item.id} data={item.data} />]
    case 'miniprogram':
      return ['小程序', <MiniProgramRecord key={item.id} data={item.data} />]
    case 'videonum':
      return ['视频号', <VideonumRecord key={item.id} data={item.data} />]
    default:
      return ['abc', <></>]
  }
}

function TextRecord(props: { data: string; onUpdate: (data: string) => void }) {
  const { data, onUpdate } = props
  return <Input.TextArea
    value={data}
    onChange={e => onUpdate(e.target.value)}
    maxLength={1000}
    autoSize={{ minRows: 3, maxRows: 5 }}
  />
}

function ImageRecord(props: { data: string }) {
  const { data } = props
  return <Link href={data}>
    <img styleName="record-image" src={data} />
  </Link>
}

function FileRecord(props: { data: string }) {
  const { data } = props
  const nodes = data.split('/')
  const name = nodes[nodes.length - 1] ?? data
  return <Link styleName="record-file" download={name} href={data}>
    文件：{name}
  </Link>
}

function VideoRecord(props: { data: string }) {
  const { data } = props
  return <video styleName="record-video" controls>
    <source src={data} type="video/mp4"></source>
  </video>
}

function LinkRecord(props: {
  data: { title: string; desc?: string; url: string; imageUrl?: string }
}) {
  const { data } = props
  return <Link styleName="record-card" href={data.url}>
    <div styleName="img" style={{ backgroundImage: `url("${data.imageUrl ?? ''}")` }} />
    <div styleName="info">
      <header>{data.title}</header>
      <div styleName="desc">{data.desc}</div>
    </div>
  </Link>
}

function MiniProgramRecord(props: { data: number }) {
  const { data } = props
  const [miniPrograms] = useStreams(services.resources.miniPrograms.list)
  const content = miniPrograms.find(v => v.id === data)
  if (!content) return <div>找不到此小程序（id: {data}）</div>

  return <div styleName="record-mini-program">
    <header>
      <img src={content.cover_path} />
      <span>{content.appname}</span>
    </header>
    <div styleName="title">{content.title}</div>
    <div styleName="footer">
      <MpIcon />
      小程序
    </div>
  </div>
}

function VideonumRecord(props: { data: number }) {
  const { data } = props
  const [videonums] = useStreams(services.resources.videonums.list)
  const content = videonums.find(v => v.id === data)
  if (!content) return <div>找不到此视频号（id: {data}）</div>

  return <div styleName="record-videonum">
    <div styleName="thumb" style={{ backgroundImage: `url(${content.cover_url})` }}></div>
    <div styleName="info">
      <img src={content.avatar} />
      <Typography.Paragraph ellipsis={{ rows: 2 }}>{content.desc}</Typography.Paragraph>
    </div>
    <div styleName="footer">
      <VideonumIcon />
      视频号
    </div>
  </div>
}
